<?php


namespace App\Services;


use App\Exceptions\ApiException;
use App\Models\ActionLog;
use App\Models\Company;
use App\Models\CompanyUser;
use App\Models\DepartmentUser;
use App\Models\PartCompanyUser;
use App\Models\ProjectUser;
use App\Models\Role;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use PHPUnit\Util\Exception;

class UserService extends BaseService
{
    /**
     * 通过用户名或手机号回去用户信息
     *
     * @param $params
     * @return array
     */
    public static function getUserByAccount($params)
    {
        try {
            $phone    = $params['phone'];
            $password = $params['password'];
            $info     = User::query()
                ->where('phone', $phone)
                ->select('id', 'nickname', 'phone', 'sex', 'status')
                ->first();
            if (empty($info)) {
                throw new Exception('用户不存在！');
            }
            $credentials = ['phone' => $phone, 'password' => $password];
            $token       = auth('api')->attempt($credentials) ?: '';
            if (!$token) {
                throw new Exception('密码错误！请联系管理员');
            }
            return [
                'user'  => $info,
                'token' => $token,
            ];
        } catch (Exception $exception) {
            return ['msg' => $exception->getMessage()];
        }
    }

    /**
     * getUserInfo
     */
    public static function getUserInfo($id)
    {
        return User::query()->find($id);
    }

    /**
     * 通过名字获取用户
     * 索引：后置百分号可以用到索引，前置百分号和两侧百分号用不了索引
     */
    public function getUsers($name)
    {
        $list = User::query()
            ->where('nickname', 'like', "%{$name}%")
            ->select('id', 'nickname', 'phone')
            ->orderBy('id')
            ->get();

        return $list->isNotEmpty() ? $list->toArray() : [];
    }

    /**
     * 通过手机号查找用户
     */
    public static function getUserByPhone($phone)
    {
        return User::query()->where('phone', $phone)->where('status', 1)->first();
    }

    /**
     * 支持对 ID、手机号精确查找，姓名模糊查找
     */
    public function getList(array $params, $perPage)
    {
        if ($params['type'] == 4) { //已删除的用户
            $thisQuery = User::onlyTrashed();
        } else {
            $thisQuery = User::query()->with(["roles", "companies", "departments", "projects", "partCompanies"])->orderByDesc('id');
        }
        if (request()->filled('company_id') && $params['company_id']) {
            $userIds = CompanyUser::query()->where('company_id', $params['company_id'])->pluck('user_id');
            if ($userIds->isNotEmpty()) {
                $userIds = $userIds->toArray();
                $thisQuery->whereIn('id', $userIds);
            }
        }
        if (request()->filled('project_id') && $params['project_id']) {
            $userIds = ProjectUser::query()->where('project_id', $params['project_id'])->pluck('user_id');
            if ($userIds->isNotEmpty()) {
                $userIds = $userIds->toArray();
                $thisQuery->whereIn('id', $userIds);
            }
        }
        if (request()->filled('keyword') && !empty($params['keyword'])) {
            $keyword = $params['keyword'];
            if ($params['type'] == 2) {
                $thisQuery->where('phone', 'like', "%{$keyword}%");
            } elseif ($params['type'] == 3) {
                $thisQuery->where('id', '=', $keyword);
            } else {
                $thisQuery->where('nickname', 'like', "%{$keyword}%");
            }
        }
        $list = $thisQuery->paginate($perPage);

        if ($list->isEmpty()) return [];

        $list = $list->toArray();
        foreach ($list['data'] as &$val) {
            $val['sex']            = to_int($val['sex']);
            $val['created_at']     = date('Y-m-d H:i', strtotime($val['created_at']));
            $val['login_time']     = $val['last_login_time'] ? date('Y-m-d H:i', strtotime($val['last_login_time'])) : '';
            $val['is_super_admin'] = 0;
            $val['login_address']  = '从未登录';
            if ($val['deleted_at']) { //如果被删除了
                $val['status'] = 3;
            }
            if ($val['last_login_ip']) {
                $result               = CommonService::getRequestAddress(@long2ip($val['last_login_ip']));
                $val['login_address'] = $result['address'];
            }
            if (in_array($val['id'], config('site.super_ids'))) { //超管
                $val['roles']          = [
                    [
                        'id'         => 1,
                        'company_id' => 0,
                        'title'      => '超管（启程）',
                        'status'     => 1
                    ]
                ];
                $val['is_super_admin'] = 1;
                $val['no_hash_pwd']    = '*********';
            }
        }

        return $this->removeNoUsedPageParams($list);
    }

    /**
     * 查找单个数据
     * 在用户列表不传 $companyId，在组织架构传$companyId，注意！接收参数在User模型里面方法：public function roles(): BelongsToMany
     *
     * @param int $id
     * @return array
     * @author: lxk
     * @date: 2024/3/27 9:48
     */
    public function getInfo(int $id): array
    {
        $user = User::query()->with('companies.roles')->where('id', $id)->first();
        if (empty($user)) {
            return [];
        } else {
            $user = $user->toArray();
        }
        $list = CompanyUser::query()
            ->where('user_id', $id)
            ->select('role_id')
            ->get();
        foreach ($user['companies'] as &$val) {
            foreach ($val['roles'] as $key2 => &$val2) {
                $val2['select'] = 0;
                foreach ($list as $val3) { //如果用户具备了某个角色， select=1 标记
                    if ($val2['id'] == $val3['role_id']) {
                        $val2['select'] = 1;
                    }
                }
                if ($val2['title'] == '公司管理员') { //公司只能有一个管理员，编辑用户时，角色里面把【公司管理员】移除，避免勾选
                    unset($val['roles'][$key2]);
                }
            }
            $val['roles'] = array_values($val['roles']);
        }

        return $user;
    }

    /**
     * 新增用户
     * @param $params
     * @return bool
     * @throws ApiException
     * @author: lxk
     * @date: 2024/2/26 10:29
     */
    public function saveBaseData($params): bool
    {
        if ($params['id']) {
            $user  = User::query()->find($params['id']);
            $info1 = User::query()->where('nickname', $params['nickname'])->where('id', '!=', $params['id'])->first();
            $info2 = User::query()->where('phone', $params['phone'])->where('id', '!=', $params['id'])->first();
        } else {
            $user  = new User();
            $info1 = User::query()->where('nickname', $params['nickname'])->first();
            $info2 = User::query()->where('phone', $params['phone'])->first();
        }
        if ($info1) throw new ApiException('用户名已存在！');
        if ($info2) throw new ApiException('手机号已存在！');
        $user->nickname = $params['nickname'];
        $user->phone    = $params['phone'];
        $user->sex      = $params['sex'];
        if ($params['password']) {
            $user->password    = $params['password'];
            $user->no_hash_pwd = $params['password'];
        } else {
            $user->password    = $params['phone'];
            $user->no_hash_pwd = $params['phone'];
        }
        $user->status = 1;
        if (!$user->save()) {
            throw new ApiException('保存失败！');
        }

        return true;
    }

    /**
     * 在用户列表 更新用户信息 （含角色）
     */
    public function updateData($params)
    {
        DB::beginTransaction();
        try {
            $user = User::query()->find($params['id']);
            if (empty($user)) {
                throw new ApiException('用户不存在');
            }
            $user->nickname    = $params['nickname'];
            $user->phone       = $params['phone'];
            $user->password    = $params['no_hash_pwd']; //模型会自动加密
            $user->no_hash_pwd = $params['no_hash_pwd'];
            $user->sex         = $params['sex'];
            $user->status      = $params['status'];
            $user->save();

            $roleIds   = to_array($params['roles']);
            $userRoles = Role::query()->whereIn('id', $roleIds)->select(['id', 'company_id'])->get()->toArray();
            /**
             * [48 => 3, 58 => 2] , 意味着指定公司id下选了几个角色
             * 要求同一用户，在一个公司，只能有一个角色
             */
            $companyRoleCounts = array_count_values(array_column($userRoles, 'company_id')); //返回数组如 [48 => 3, 58 => 2]
            $companyRoleCounts = array_values($companyRoleCounts); //回数组如 [3, 2]
            foreach ($companyRoleCounts as $count) {
                if ($count > 1) {
                    throw new Exception('用户不能在一个公司有多个角色！');
                }
            }
            $insertData = [];
            foreach ($userRoles as $val) {
                $insertData[$val['id']] = [ //构造一个包含额外数据的数组
                    'company_id' => $val['company_id'],
                    'creator_id' => user_id(),
                    'created_at' => now(),
                    'updated_at' => now(),
                ];
            }
            $user->roles()->sync($insertData); //中间表数据写入
            del_user_rule_menus($params['id']); //清除菜单权限缓存 重新获取

            CommonService::addActionLog('修改用户信息');
            DB::commit();
            return ['msg' => ''];
        } catch (Exception $exception) {
            DB::rollBack();
            return ['msg' => $exception->getMessage()];
        }
    }

    /**
     * 在组织架构里面更新用户
     */
    public function updateUserInOrganize($params)
    {
        $user = User::query()->find($params['id']);

        if ($user->phone != $params['phone']) { //更新密码
            $user->password    = $params['phone'];
            $user->no_hash_pwd = $params['phone'];
        }
        $user->nickname = $params['nickname'];
        $user->phone    = $params['phone'];
        $user->sex      = $params['sex'];
        $user->status   = $params['status'];
        $user->save();

        $info = CompanyUser::query()
            ->where('company_id', $params['company_id'])
            ->where('user_id', $params['id'])
            ->first();
        if ($info) {
            $info->update(['role_id' => $params['roleId']]);
        } else {
            $companyUser             = new CompanyUser();
            $companyUser->company_id = $params['company_id'];
            $companyUser->user_id    = $params['user_id'];
            $companyUser->role_id    = $params['role_id'];
            $companyUser->company_id = $params['company_id'];
            $companyUser->creator_id = user_id();
            $companyUser->save();
        }
    }

    /**
     * 获取已删除数据（回收站）
     */
    public function getRecycles($request): array
    {
        $thisQuery = User::onlyTrashed();

        if ($request->filled('keyword')) { //判断参数是否存在并且不为空
            $keyword = $request->input('keyword');
            $thisQuery->where('nickname', 'like', "%{$keyword}%"); //由于不同的表字段不同，所以单独拿出来
        }

        return $this->formatRecycleData($request, $thisQuery);
    }

    /**
     * 将用户选择的companyId放到Cache缓存
     */
    public function setCompanyId($companyId = 0)
    {
        $user     = user();
        $cacheKey = cache_key();

        $roleId = CompanyUser::query()->where('company_id', $companyId)->where('user_id', $user->id)->value('role_id');

        if (!is_super_admin() && !$roleId) throw new ApiException('您在这个公司没有角色，请联系管理员~');

        Cache::put('companyId:' . $cacheKey, $companyId);

        $this->setUserCompanyRoleCache($user->id, $cacheKey);

        CommonService::addActionLog('用户登录', '登录成功~');

        return $user;
    }

    /**
     * 登录后，获取用户当前的公司和角色
     */
    public function setUserCompanyRoleCache($userId, $cacheKey)
    {
        Cache::forget('companyName:' . $cacheKey);
        Cache::forget('companyRole:' . $cacheKey);

        $companyId = company_id();
        $roleId    = CompanyUser::query()
            ->where('company_id', $companyId)
            ->where('user_id', $userId)
            ->value('role_id');

        $roleName    = is_super_admin() ? "超管（启程）" : Role::query()->where('id', $roleId)->value('title');
        $companyName = Company::query()->where('id', $companyId)->value('title');

        Cache::put('companyName:' . $cacheKey, $companyName);
        Cache::put('companyRole:' . $cacheKey, $roleName);
    }

    /**
     * 获取用户所在的公司列表
     *
     * @return array
     * @author: lxk
     * @date: 2024/3/21 10:58
     */
    public function companies(): array
    {
        if (is_super_admin()) { //超级管理员，返回全部公司供选择
            $user            = User::query()->where('id', user_id())->select('id', 'nickname')->first();
            $companies       = Company::query()->where('status', 1)->select('id', 'title')->get();
            $user->companies = $companies;
        } else { //仅返回关联公司
            $user = User::with('companies:id,title')
                ->where('id', user_id())
                ->first();
        }
        return !empty($user) ? $user->toArray() : [];
    }

    /**
     * 获取当前登录用户所在的全部公司，以及在每个公司全部的角色
     * 批量pdf上传提示和限制
     */
    public function userDetails($userId)
    {
        $user = User::query()->select('id', 'phone', 'nickname', 'sex')->find($userId);
        if (is_super_admin()) { //获取全部
            $companyList = Company::query()->select('id', 'title')->get()->toArray();
        } else {
            $companyIds  = CompanyUser::query()
                ->where('user_id', $userId)
                ->select('company_id')
                ->pluck('company_id');
            $companyList = Company::query()->whereIn('id', $companyIds)->select('id', 'title')->get()->toArray();
        }
        $switchList = $companyList; //把原始值存起来，切换公司用
        foreach ($companyList as &$company) {
            $roleIds          = CompanyUser::query()
                ->where('user_id', $userId)
                ->where('company_id', $company['id'])
                ->pluck('role_id')
                ->toArray();
            $company['roles'] = Role::query()->whereIn('id', $roleIds)->select('id', 'title')->get()->toArray();
        }
        $user['companies']        = $companyList;
        $user['is_super_admin']   = is_super_admin();
        $user['is_company_admin'] = CommonService::isAdmin();
        $user['admin_level']      = CommonService::adminLevel();
        //$user['is_owner']              = CommonService::isAdmin();
        $user['company_name']            = Cache::get('companyName:' . cache_key());
        $user['company_role']            = Cache::get('companyRole:' . cache_key());
        $user['switch_list']             = $switchList;
        $upFileCount                     = config('site.up_file_count');
        $user['batch_upload_pdf_notice'] = "批量上传最多{$upFileCount}个文件；绿色图标代表单个文件上传成功";
        $user['batch_upload_pdf_limit']  = $upFileCount;
        $user['company_id']              = company_id();

        return $user;
    }

    /**
     * 获取查找的用户所在公司和角色
     */
    public function getUserCompanyRoles($userId)
    {
        $user        = User::query()->select('id', 'phone', 'nickname', 'sex')->find($userId);
        $companyIds  = CompanyUser::query()
            ->where('user_id', $userId)
            ->select('company_id')
            ->pluck('company_id');
        $companyList = Company::query()->whereIn('id', $companyIds)->select('id', 'title')->get()->toArray();
        foreach ($companyList as &$company) {
            $roleIds          = CompanyUser::query()
                ->where('user_id', $userId)
                ->where('company_id', $company['id'])
                ->pluck('role_id')
                ->toArray();
            $company['roles'] = Role::query()->whereIn('id', $roleIds)->select('id', 'title')->get()->toArray();
        }
        $user['companies'] = $companyList;

        return $user;
    }


    /**
     * 获取操作记录数据
     * search_type: 1公司, 2操作人, 3角色名, 4事件, 5详情
     */
    public function getActionLogList($request, $perPage)
    {
        $baseQuery = ActionLog::query();
        if ($request->filled('keyword')) {
            $searchType = $request->input('search_type');
            $keyword    = $request->input('keyword');
            switch ($searchType) {
                case 1: //操作人
                    $baseQuery->where('user_name', 'like', "%{$keyword}%");
                    break;
                case 2: //公司
                    $baseQuery->where('company_name', 'like', "%{$keyword}%");
                    break;
                case 3: //角色名
                    $baseQuery->where('role_name', 'like', "%{$keyword}%");
                    break;
                case 4: //事件
                    $baseQuery->where('event', 'like', "%{$keyword}%");
                    break;
                case 5: //详情
                    $baseQuery->where('detail', 'like', "%{$keyword}%");
                    break;
                default: //详情
                    $baseQuery->where('detail', 'like', "%{$keyword}%");
            }
        }
        if ($request->filled('date_range')) {
            $dateRange = $request->input('date_range');
            $baseQuery->whereBetween('created_at', $dateRange);
        }
        if (!is_super_admin()) { //如果不是超管，只看到本公司的人员操作记录
            $baseQuery->where('company_id', company_id());
        }
        $list = $baseQuery
            ->select('id', 'company_name', 'user_name', 'role_name', 'event', 'detail', 'action_ip', 'address', 'created_at')
            ->orderByDesc('id')
            ->paginate($perPage);

        if ($list->isEmpty()) return [];
        $list = $list->toArray();
        foreach ($list['data'] as &$val) {
            $val['created_at'] = date('Y-m-d H:i', strtotime($val['created_at']));
            $val['address']    = $val['address'] ?: '本地登录';
        }

        return $this->removeNoUsedPageParams($list);
    }

    /**
     * 转让管理员
     */
    public function transferAdmin($phone, $nickname)
    {
        $tmpUser = UserService::getUserByPhone($phone); //新管理员
        if (!empty($tmpUser)) {
            $userId = $tmpUser->id;
        } else {
            $user              = new User();
            $user->phone       = $phone;
            $user->nickname    = $nickname;
            $user->password    = $phone; //初始密码为手机号
            $user->no_hash_pwd = $phone;
            $user->status      = 1;
            $user->save();
            $userId = $user->id;
        }
        $newUserInfo = CompanyUser::query()
            ->where('company_id', company_id())
            ->where('user_id', $userId)
            ->first();
        if ($newUserInfo) { //如果用户在公司原来有角色，删除
            $newUserInfo->delete();
        }
        //查出这个公司原来的管理员id
        $roleId = Role::query()
            ->where('company_id', company_id())
            ->where('admin_level', 2) //'0非管理员;1超管,2公司管理员,3副管理员',
            ->where('status', 1)
            ->value('id');

        CompanyUser::query() //把这个公司原来的管理员信息更新为新管理员
        ->where('company_id', company_id())
            ->where('user_id', user_id())
            ->where('is_admin', 1)
            ->update(['user_id' => $userId, 'role_id' => $roleId]);

        $preAdmin = user()->nickname;
        CommonService::addActionLog('转让账号', "{$preAdmin}把账号转让给{$nickname}");
    }

    /**
     * 批量修改用户密码
     *
     * @param $type
     * @param $prefix
     * @param $redisKey
     * @author: lxk
     * @date: 2025-07-24 10:51
     */
    public function resetSystemUsersPassword($type, $prefix, $redisKey)
    {
        User::query()
            ->where('id', '>', 1)
            ->chunkById(10, function ($list) use ($type, $prefix, $redisKey) {
                foreach ($list as $val) {
                    redis()->incr($redisKey);
                    $user = User::query()->find($val['id']);
                    if ($type == 1) {
                        $phoneStr          = substr($user->phone, -4); //手机尾号四位数
                        $user->password    = "$prefix@$phoneStr";
                        $user->no_hash_pwd = "$prefix@$phoneStr";
                    } else {
                        $randomStr         = create_random_num_str();
                        $user->password    = $randomStr;
                        $user->no_hash_pwd = $randomStr;
                    }
                    $user->save();
                }
            });

        CommonService::addActionLog("把系统用户密码重置,类型{$type}", );
    }

}
